/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2025-02-27     liyih       the first version
 */
#include <AD9910/AD9910_Base.hpp>
#include "AD9910_Base.hpp"

#define SPI_DEVICE_NAME "spi30"
#define SPI_BUS_NAME "spi3"
AD9910_Base::AD9910_Base()
{
    CFR1.resize(4);
    CFR2.resize(4);
    CFR3.resize(4);

    // spi configuration
    rt_hw_spi_device_attach(SPI_BUS_NAME, SPI_DEVICE_NAME, GPIOF, GPIO_PIN_3);

    rt_spi_configuration cfg;
    cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB; /* 模式 */
    cfg.data_width = 8;                                    /* 数据宽度，可取8位、16位、32位 */
    cfg.max_hz = 1 * 1000 * 1000;                          /* 最大频率 */
    spi_dev = (rt_spi_device *)rt_device_find(SPI_DEVICE_NAME);
    if (!spi_dev)
    {
        rt_kprintf("spi sample run failed! can't find %s device!\n", SPI_DEVICE_NAME);
    }
    else
    {
        rt_spi_configure(spi_dev, &cfg);
    }
}

AD9910_Base::~AD9910_Base()
{
    // TODO 自动生成的析构函数存根
}

void AD9910_Base::IO_config()
{
    rt_pin_mode(PIN_PWR, PIN_MODE_OUTPUT);
    // rt_pin_mode(PIN_SDIO, PIN_MODE_OUTPUT);// used by SPI driver
    rt_pin_mode(PIN_DPH, PIN_MODE_OUTPUT);
    rt_pin_mode(PIN_DRO, PIN_MODE_OUTPUT);
    rt_pin_mode(PIN_IOUP, PIN_MODE_OUTPUT);
    rt_pin_mode(PIN_PF0, PIN_MODE_OUTPUT);
    rt_pin_mode(PIN_PF1, PIN_MODE_OUTPUT);
    rt_pin_mode(PIN_PF2, PIN_MODE_OUTPUT);
    rt_pin_mode(PIN_RST, PIN_MODE_OUTPUT);
    // rt_pin_mode(PIN_SCK, PIN_MODE_OUTPUT);// used by SPI driver
    rt_pin_mode(PIN_DRC, PIN_MODE_OUTPUT);
    rt_pin_mode(PIN_OSK, PIN_MODE_OUTPUT);
    // rt_pin_mode(PIN_CSB, PIN_MODE_OUTPUT);// used by SPI driver
}

void AD9910_Base::module_init()
{
    IO_config();
    setDefaultCFR();

    power_reset();

    //* select profile 0
    rt_pin_write(PIN_PF0, 0);
    rt_pin_write(PIN_PF1, 0);
    rt_pin_write(PIN_PF2, 0);
    rt_pin_write(PIN_DRC, 0);
    rt_pin_write(PIN_DPH, 0);

    module_reset();

    spi_sendData(REG_CFR1, CFR1);
    spi_sendData(REG_CFR2, CFR2);
    spi_sendData(REG_CFR3, CFR3);
}

void AD9910_Base::power_reset()
{
    rt_pin_write(PIN_PWR, 1);
    rt_thread_mdelay(1);
    rt_pin_write(PIN_PWR, 0);
    rt_thread_mdelay(1);
}

void AD9910_Base::IO_update()
{
    rt_pin_write(PIN_IOUP, 0); // 更新AD9910
    rt_pin_write(PIN_IOUP, 1);
    rt_pin_write(PIN_IOUP, 0);
}

void AD9910_Base::IO_reset()
{
    rt_pin_write(PIN_CSB, 0);
    rt_pin_write(PIN_CSB, 1);
    rt_pin_write(PIN_CSB, 0);
}

void AD9910_Base::module_reset()
{
    rt_pin_write(PIN_RST, 0);
    rt_thread_mdelay(1);
    rt_pin_write(PIN_RST, 1);
    rt_thread_mdelay(1);
    rt_pin_write(PIN_RST, 0);
}

void AD9910_Base::setDefaultCFR()
{
    CFR1 = {0x00, 0x40, 0x00, 0x00}; // 反Sinc滤波器使能
    CFR2 = {0x01, 0x00, 0x00, 0x00}; // 使能单频profile调制幅度
    CFR3 = {0x05, 0x0F, 0x41, 0x32}; // VC0 = 0b101(VCO5); ICP = 0b001(237uA); 输入分频器正常工作; REFCLK PLL使能; 分频模数 = 0b11001(25倍频); 40MHz输入 * 25倍频 = 1GHz主频
}

rt_err_t AD9910_Base::spi_sendData(const uint8_t reg, const std::vector<uint8_t> &data)
{
    //* reset IO before send data
    IO_reset();
    rt_thread_mdelay(1);

    rt_err_t ret = rt_spi_send_then_send(spi_dev, &reg, 1, data.data(), data.size());
    rt_thread_mdelay(1);

    //* update IO after send data
    IO_update();

    return ret;
}

rt_err_t AD9910_Base::spi_sendRam(const std::vector<uint32_t> &data)
{
    //* reset IO before send data
    IO_reset();
    rt_thread_mdelay(1);

    const size_t dataSize = data.size() > 1024 ? 1024 : data.size();
    std::vector<uint8_t> dataByte(dataSize * 4, 0);
    for (size_t i = 0; i < dataSize; i++)
    {
        // 将波形数据数组写入ram,32位寄存器，14位DAC值，数据左对齐，故左移18位
        uint32_t shiftData = data[i] << 18;
        dataByte[i * sizeof(uint32_t) + 0] = (shiftData >> 24) & 0xFF;
        dataByte[i * sizeof(uint32_t) + 1] = (shiftData >> 16) & 0xFF;
        dataByte[i * sizeof(uint32_t) + 2] = (shiftData >> 8) & 0xFF;
        dataByte[i * sizeof(uint32_t) + 3] = (shiftData >> 0) & 0xFF;
    }
    const uint8_t reg = REG_RAM;

    rt_err_t ret = rt_spi_send_then_send(spi_dev, &reg, 1, dataByte.data(), dataByte.size());

    //* update IO after send data
    // IO_update();
    // rt_thread_mdelay(1);

    return ret;
}

rt_err_t AD9910_Base::spi_readRam(std::vector<uint32_t> &data)
{
    //* reset IO before read data
    IO_reset();
    rt_thread_mdelay(1);

    std::vector<uint8_t> recvData(4096);
    const uint8_t reg = REG_RAM | READ_REG;
    rt_err_t ret = rt_spi_transfer(spi_dev, &reg, recvData.data(), 4096);

    data.resize(1024);
    if (ret == RT_EOK)
    {
        for (size_t i = 0; i < recvData.size(); i += 4)
        {
            data[i / 4] = ((recvData[i + 0] << 24) | (recvData[i + 1] << 16) | (recvData[i + 2] << 8) | (recvData[i + 3] << 0)) >> 18;
        }
    }

    //* update IO after read data
    // IO_update();
    // rt_thread_mdelay(1);

    return ret;
}
